home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connectio…eloper Series 2005 March / Dev.CD Mar 05.iso / What's New / Technical Notes and Q&As / ADC Reference Library / qa / qa2001 / downloads / qa1027.hqx / DrawUnicodeString / DrawUnicodeString.c next >
Encoding:
C/C++ Source or Header  |  2001-04-12  |  10.9 KB  |  355 lines

  1.  
  2. #include "DrawUnicodeString.h"
  3.  
  4. #if ! TARGET_API_MAC_CARBON
  5.  
  6. #include <Script.h>
  7.  
  8. #endif
  9.  
  10.  
  11.     /* MakeThemeATSUIStyle creates a simple ATSUI style record that
  12.     based on the current theme fond that can be used in calls to the
  13.     RenderCFString routine. */ 
  14. OSStatus MakeThemeATSUIStyle(ThemeFontID themeFontID, ATSUStyle *theStyle) {
  15.     OSStatus err;
  16.     ATSUStyle localStyle;
  17.     ATSUFontID atsuFont;
  18.     Fixed atsuSize;
  19.     short atsuOrientation, fontFamily, fontSize;
  20.     Str255 fontName;
  21.     Style fontStyle;
  22.     Boolean trueVar = true, falseVar = false;
  23.     
  24.         /* Three parrallel arrays for setting up attributes. */
  25.     ATSUAttributeTag theTags[] = {
  26.             kATSUFontTag, kATSUSizeTag, kATSUVerticalCharacterTag,
  27.             kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, 
  28.             kATSUQDCondensedTag, kATSUQDExtendedTag
  29.         };
  30.     ByteCount theSizes[] = {
  31.             sizeof(ATSUFontID), sizeof(Fixed), sizeof(UInt16),
  32.             sizeof(Boolean), sizeof(Boolean), sizeof(Boolean),
  33.             sizeof(Boolean), sizeof(Boolean)
  34.         };
  35.     ATSUAttributeValuePtr theValues[] = {
  36.             NULL, NULL, NULL, NULL,
  37.             NULL, NULL, NULL, NULL
  38.         };
  39.         
  40.         /* set up locals */
  41.     localStyle = NULL;
  42.     atsuFont = 0;
  43.     atsuSize = 0x00080000;
  44.     atsuOrientation = kATSUStronglyHorizontal; /* kATSUStronglyVertical */
  45.     
  46.         /* calculate the theme font parameters */
  47.     err = GetThemeFont( themeFontID, smSystemScript,
  48.             fontName,  &fontSize, &fontStyle);
  49.     if (err != noErr) goto bail;
  50.     atsuSize = FixRatio(fontSize, 1);
  51.     
  52.         /* set the values array to point to our locals */
  53.     theValues[0] = &atsuFont;
  54.     theValues[1] = &atsuSize;
  55.     theValues[2] = &atsuOrientation;
  56.     theValues[3] = ((fontStyle & bold) != 0 ? &trueVar : &falseVar);
  57.     theValues[4] = ((fontStyle & italic) != 0 ? &trueVar : &falseVar);
  58.     theValues[5] = ((fontStyle & underline) != 0 ? &trueVar : &falseVar);
  59.     theValues[6] = ((fontStyle & condense) != 0 ? &trueVar : &falseVar);
  60.     theValues[7] = ((fontStyle & extend) != 0 ? &trueVar : &falseVar);
  61.     
  62.         /* calculate the font ID */
  63.     GetFNum( fontName, &fontFamily);
  64.     err = ATSUFONDtoFontID( fontFamily, fontStyle, &atsuFont);
  65.     if (err != noErr) goto bail;
  66.     
  67.         /* find the font ID */
  68.     err = ATSUFindFontFromName((Ptr)fontName+1, (long)fontName[0],
  69.         kFontFullName, kFontMacintoshPlatform,
  70.         kFontRomanScript, kFontNoLanguage, &atsuFont);
  71.     if (err != noErr) goto bail;
  72.     
  73.         /* create a style */
  74.     err = ATSUCreateStyle(&localStyle);
  75.     if (err != noErr) goto bail;
  76.     
  77.         /* set the style attributes */    
  78.     err = ATSUSetAttributes( localStyle, sizeof(theTags)/sizeof(theTags[0]), theTags, theSizes, theValues );
  79.     if (err != noErr) goto bail;
  80.     
  81.         /* store the new style for the caller */    
  82.     *theStyle = localStyle;
  83.     return noErr;
  84. bail:
  85.     if (localStyle != NULL) ATSUDisposeStyle(localStyle);
  86.     return err;
  87. }
  88.  
  89.  
  90.  
  91.     /* MakeSimpleATSUIStyle creates a simple ATSUI style record that
  92.     can be used in calls to the RenderCFString routine. */ 
  93. OSStatus MakeSimpleATSUIStyle(StringPtr fontName, short fontSize, short qdStyle,
  94.             RGBColor *fontColor, ATSUStyle *theStyle) {
  95.     OSStatus err;
  96.     ATSUStyle localStyle;
  97.     ATSUFontID atsuFont;
  98.     Fixed atsuSize;
  99.     short atsuOrientation;
  100.     RGBColor defaultColor = { 0, 0, 0};
  101.     Boolean trueVar = true, falseVar = false;
  102.     
  103.         /* Three parrallel arrays for setting up attributes. */
  104.     ATSUAttributeTag theTags[] = {
  105.             kATSUFontTag, kATSUSizeTag, kATSUVerticalCharacterTag,
  106.             kATSUColorTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, 
  107.             kATSUQDUnderlineTag, kATSUQDCondensedTag, kATSUQDExtendedTag
  108.         };
  109.     ByteCount theSizes[] = {
  110.             sizeof(ATSUFontID), sizeof(Fixed), sizeof(UInt16),
  111.             sizeof(RGBColor), sizeof(Boolean), sizeof(Boolean),
  112.             sizeof(Boolean), sizeof(Boolean), sizeof(Boolean)
  113.         };
  114.     ATSUAttributeValuePtr theValues[] = {
  115.             NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
  116.         };
  117.         
  118.         /* set up locals */
  119.     localStyle = NULL;
  120.     atsuFont = 0;
  121.     atsuSize = FixRatio(fontSize, 1);
  122.     atsuOrientation = kATSUStronglyHorizontal; /* kATSUStronglyVertical */
  123.     
  124.         /* set the values array to point to our locals */
  125.     theValues[0] = &atsuFont;
  126.     theValues[1] = &atsuSize;
  127.     theValues[2] = &atsuOrientation;
  128.     theValues[3] = ((fontColor != NULL) ? fontColor : &defaultColor);
  129.     theValues[4] = ((qdStyle & bold) != 0 ? &trueVar : &falseVar);
  130.     theValues[5] = ((qdStyle & italic) != 0 ? &trueVar : &falseVar);
  131.     theValues[6] = ((qdStyle & underline) != 0 ? &trueVar : &falseVar);
  132.     theValues[7] = ((qdStyle & condense) != 0 ? &trueVar : &falseVar);
  133.     theValues[8] = ((qdStyle & extend) != 0 ? &trueVar : &falseVar);
  134.     
  135.         /* find the font ID */
  136.     err = ATSUFindFontFromName((Ptr)fontName+1, (long)fontName[0],
  137.         kFontFullName, kFontMacintoshPlatform, kFontRomanScript, 
  138.         kFontNoLanguage, &atsuFont);
  139.     if (err != noErr) goto bail;
  140.     
  141.         /* create a style */
  142.     err = ATSUCreateStyle(&localStyle);
  143.     if (err != noErr) goto bail;
  144.     
  145.         /* set the style attributes */    
  146.     err = ATSUSetAttributes( localStyle, (sizeof(theTags) / sizeof(theTags[0])), theTags, theSizes, theValues );
  147.     if (err != noErr) goto bail;
  148.     
  149.         /* store the new style for the caller */    
  150.     *theStyle = localStyle;
  151.     return noErr;
  152. bail:
  153.     if (localStyle != NULL) ATSUDisposeStyle(localStyle);
  154.     return err;
  155. }
  156.  
  157.  
  158.  
  159.     /* RenderCFString renders a CFString at (h, v) in the current grafport
  160.     using ATSUI using the style specified in the atsui style record. */
  161. OSStatus RenderUnicodeString(ConstUniCharArrayPtr iText, UniCharCount iTextLength,
  162.     ATSUStyle theStyle, short h, short v, short maxwidth)  {
  163.     ATSUTextLayout theLayout = NULL;
  164.     OSStatus err;
  165.     
  166.         /* set up our locals, verify parameters... */
  167.     if (iText == NULL || theStyle == NULL) return paramErr;
  168.     theLayout = NULL;
  169.     if (iTextLength == 0) return noErr;
  170.     
  171.         /* create the ATSUI layout */
  172.     err = ATSUCreateTextLayoutWithTextPtr( iText, 0,
  173.         iTextLength, iTextLength, 1, 
  174.         (unsigned long *) &iTextLength, &theStyle, &theLayout);
  175.     if (err != noErr) goto bail;
  176.  
  177.     if (maxwidth != 0) {
  178.         UniCharArrayOffset iLineStart, oLineBreak;
  179.         ATSUTextMeasurement iLineWidth;
  180.         long nlines;
  181.         ATSUTextMeasurement oTextBefore, oTextAfter, oAscent, oDescent;
  182.  
  183.         iLineStart = 0;
  184.         iLineWidth = FixRatio(maxwidth, 1);
  185.         nlines = 0;
  186.         err = ATSUMeasureText( theLayout, 0, iTextLength, &oTextBefore, &oTextAfter, &oAscent, &oDescent);
  187.         if (err != noErr) goto bail;
  188.         do {
  189.             err = ATSUBreakLine( theLayout, iLineStart, iLineWidth, true,  &oLineBreak);
  190.             if (err != noErr) goto bail;
  191.             err = ATSUDrawText(theLayout, iLineStart, oLineBreak - iLineStart,
  192.                 FixRatio(h, 1),
  193.                 FixRatio(v, 1) + FixMul(oAscent + oDescent, FixRatio(nlines++, 1)));
  194.             if (err != noErr) goto bail;
  195.             iLineStart = oLineBreak;
  196.         } while ((oLineBreak < iTextLength) && (nlines < iTextLength));
  197.     } else {
  198.             /* draw the text */
  199.         err = ATSUDrawText(theLayout, 0, iTextLength, FixRatio(h, 1), FixRatio(v, 1));
  200.         if (err != noErr) goto bail;
  201.     }
  202.  
  203.         /* done */
  204.     ATSUDisposeTextLayout(theLayout);
  205.     return noErr;
  206.  
  207. bail:
  208.     if (theLayout != NULL) ATSUDisposeTextLayout(theLayout);
  209.     return err;
  210. }
  211.  
  212.  
  213.     /* MeasureUnicodeString returns a rectangle where the CFStringRef would
  214.     be drawn if it were drawn at location (0,0) -- just like QDTextBounds. */
  215. OSStatus MeasureUnicodeString(ConstUniCharArrayPtr iText, UniCharCount iTextLength,
  216.         ATSUStyle theStyle, short maxwidth, Rect *bounds) {
  217.     ATSUTextLayout theLayout = NULL;
  218.     OSStatus err;
  219.     ATSUTextMeasurement oTextBefore, oTextAfter, oAscent, oDescent;
  220.     
  221.         /* set up our locals, verify parameters... */
  222.     if (iText == NULL || theStyle == NULL) return paramErr;
  223.     theLayout = NULL;
  224.     if (iTextLength == 0) return noErr;
  225.     
  226.         /* create the ATSUI layout */
  227.     err = ATSUCreateTextLayoutWithTextPtr( iText, 0,
  228.         iTextLength, iTextLength, 1, 
  229.         (unsigned long *) &iTextLength, &theStyle, &theLayout);
  230.     if (err != noErr) goto bail;
  231.     
  232.     if (maxwidth != 0) {
  233.         UniCharArrayOffset iLineStart, oLineBreak;
  234.         ATSUTextMeasurement iLineWidth;
  235.         long nlines;
  236.         ATSUTextMeasurement oTextBefore, oTextAfter, maxTextAfter, oAscent, oDescent;
  237.  
  238.         iLineStart = 0;
  239.         iLineWidth = FixRatio(maxwidth, 1);
  240.         nlines = 0;
  241.         maxTextAfter = 0;
  242.         do {
  243.             err = ATSUBreakLine( theLayout, iLineStart, iLineWidth, true,  &oLineBreak);
  244.             if (err != noErr) goto bail;
  245.             err = ATSUMeasureText( theLayout, iLineStart, oLineBreak - iLineStart,
  246.                 &oTextBefore, &oTextAfter, &oAscent, &oDescent);
  247.             if (err != noErr) goto bail;
  248.             nlines++;
  249.             if (maxTextAfter < oTextAfter) maxTextAfter = oTextAfter;
  250.             iLineStart = oLineBreak;
  251.         } while ((oLineBreak < iTextLength) && (nlines < iTextLength));
  252.         SetRect(bounds,
  253.             - FixRound(oTextBefore),
  254.             - FixRound(oAscent),
  255.             FixRound(maxTextAfter),
  256.             FixRound(oDescent + FixMul(oAscent + oDescent, FixRatio(nlines-1, 1))));
  257.     } else {
  258.             /* measure the text */
  259.         err = ATSUMeasureText( theLayout, 0, iTextLength,
  260.             &oTextBefore, &oTextAfter, &oAscent, &oDescent);
  261.         if (err != noErr) goto bail;
  262.         SetRect(bounds,
  263.             - FixRound(oTextBefore),
  264.             - FixRound(oAscent),
  265.             FixRound(oTextAfter),
  266.             FixRound(oDescent)+1);
  267.     }
  268.     
  269.         /* done */
  270.     ATSUDisposeTextLayout(theLayout);
  271.     return noErr;
  272.  
  273. bail:
  274.     if (theLayout != NULL) ATSUDisposeTextLayout(theLayout);
  275.     return err;
  276. }
  277.  
  278.  
  279.  
  280.  
  281. #if TARGET_API_MAC_CARBON
  282.  
  283.  
  284.     /* RenderCFString renders a CFString at (h, v) in the current grafport
  285.     using ATSUI using the style specified in the atsui style record. */
  286. OSStatus RenderCFString(CFStringRef theString, ATSUStyle theStyle, short h, short v, short maxwidth) {
  287.     CFIndex textLength;
  288.     OSStatus err;
  289.     UniChar *uniBuffer;
  290.     CFRange uniRange;
  291.     
  292.         /* set up our locals, verify parameters... */
  293.     if (theString == NULL || theStyle == NULL) return paramErr;
  294.     uniBuffer = NULL;
  295.     textLength = CFStringGetLength(theString);
  296.     if (textLength == 0) return noErr;
  297.     
  298.         /* get our data */
  299.     uniRange = CFRangeMake(0, textLength);
  300.     uniBuffer = (UniChar *) NewPtr( textLength * sizeof(UniChar) );
  301.     if (uniBuffer == NULL) { err = memFullErr; goto bail; }
  302.     CFStringGetCharacters( theString,  uniRange, uniBuffer);
  303.     
  304.         /* render the string */
  305.     err = RenderUnicodeString(uniBuffer, textLength, theStyle, h, v, maxwidth);
  306.     if (err != noErr) goto bail;
  307.     
  308.         /* clean up */
  309.     DisposePtr((Ptr) uniBuffer);
  310.     
  311.         /* leave */
  312.     return noErr;
  313. bail:
  314.     if (uniBuffer != NULL) DisposePtr((Ptr) uniBuffer);
  315.     return err;
  316. }
  317.  
  318.  
  319.     /* MeasureCFString returns a rectangle where the CFStringRef would
  320.     be drawn if it were drawn at location (0,0) -- just like QDTextBounds. */
  321. OSStatus MeasureCFString(CFStringRef theString, ATSUStyle theStyle, short maxwidth, Rect *bounds) {
  322.     CFIndex textLength;
  323.     OSStatus err;
  324.     UniChar *uniBuffer;
  325.     CFRange uniRange;
  326.     
  327.         /* set up our locals, verify parameters... */
  328.     if (theString == NULL || theStyle == NULL) return paramErr;
  329.     uniBuffer = NULL;
  330.     textLength = CFStringGetLength(theString);
  331.     if (textLength == 0) return noErr;
  332.     
  333.         /* get our data */
  334.     uniRange = CFRangeMake(0, textLength);
  335.     uniBuffer = (UniChar *) NewPtr( textLength * sizeof(UniChar) );
  336.     if (uniBuffer == NULL) { err = memFullErr; goto bail; }
  337.     CFStringGetCharacters( theString,  uniRange, uniBuffer);
  338.     
  339.         /* render the string */
  340.     err = MeasureUnicodeString(uniBuffer, textLength, theStyle, maxwidth, bounds);
  341.     if (err != noErr) goto bail;
  342.     
  343.         /* clean up */
  344.     DisposePtr((Ptr) uniBuffer);
  345.     
  346.         /* leave */
  347.     return noErr;
  348. bail:
  349.     if (uniBuffer != NULL) DisposePtr((Ptr) uniBuffer);
  350.     return err;
  351. }
  352.  
  353.  
  354. #endif
  355.